import asyncio
import qasync
from MyTT import EMA
import numpy as np
import pandas as pd
from tqsdk import TqApi
from db_manager import connect_db, get_monitored_products
import time

class AsyncOpenCloseStrategy:
    """异步开平仓策略"""
    def __init__(self, api: TqApi, symbols, lots=1):
        super().__init__()
        self.api = api
        self.symbols = symbols
        self.lots = lots
        self.running = False
        self.main_task = None
        self.active_symbols = set()  # 新增运行状态跟踪

    async def start(self):
        """启动策略（协程版本）"""
        print("************************已启动策略************************")
        self.running = True
        # 确保每次启动都创建新任务
        if self.main_task:
            self.main_task.cancel()
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(self._run_all_symbols())
        loop.close()
        #self.main_task  = await self._run_all_symbols()  # 新增返回任务对象
        #self.main_task  = self._run_all_symbols()  # 新增返回任务对象
        return self.main_task  # 新增返回任务对象

    async def _run_all_symbols(self):
        """并行处理所有品种"""
        # 添加任务执行日志
        print(f"开始处理品种列表: {self.symbols}") 
        tasks = [asyncio.create_task(self._process_product(symbol)) for symbol in self.symbols]
        await asyncio.gather(*tasks)

    async def _process_product(self, symbol):
        """单个品种处理协程"""
        self.active_symbols.add(symbol)
        print(f"开始处理品种: {symbol}")  # 添加日志
        try:
            klines = self.api.get_kline_serial(symbol, 300, 500)
            
            # # 在策略启动后检查
            # if strategy.main_task and not strategy.main_task.done():
            #     print(f"当前运行品种: {strategy.active_symbols}")
            
            while self.running:
                # 添加数据更新等待
                #deadline=time.time()
                #await self.api.wait_update(deadline=deadline+0.5)                
                print(f"{symbol} 正在运行...", flush=True)  # 添加flush确保及时输出
                await asyncio.sleep(1)
                if self.api.is_changing(klines.iloc[-1], "datetime"):
                    if not klines.close.iloc[-1]:
                        print("K线已变化")
                        q = (3*klines.close + klines.low + klines.open + klines.high) / 6
                        ma_values = self._calculate_ma(q)
                        short_ma = ma_values['ma']
                        ema_7 = ma_values['ema']
                        
                        position = self.api.get_position(symbol)
                        
                        # 平空仓逻辑
                        if short_ma[-2] > ema_7[-2]:  
                            if position.pos_short > 0:
                                self.api.insert_order(symbol, direction="BUY", offset="CLOSE", 
                                                volume=position.pos_short)
                        # 开多仓逻辑
                        if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] < ema_7[-3] and short_ma[-2] > ema_7[-2]:
                            self.api.insert_order(symbol, direction="BUY", offset="OPEN", 
                                            volume=self.lots)
                            
                        # 平多仓逻辑
                        if short_ma[-2] < ema_7[-2]:  
                            if position.pos_long > 0:
                                self.api.insert_order(symbol, direction="SELL", offset="CLOSE", 
                                                volume=position.pos_long)
                        # 开空仓逻辑
                        if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] > ema_7[-3] and short_ma[-2] < ema_7[-2]:
                            self.api.insert_order(symbol, direction="SELL", offset="OPEN", 
                                            volume=self.lots)

        except Exception as e:
            print(f"处理品种 {symbol} 时出错: {e}")
        finally:
            self.active_symbols.remove(symbol)

    def _calculate_ma(self, q):
        """自定义权重计算（与原版完全一致）"""
        weights = np.arange(26, 0, -1)
        ma = []
        q_array = np.array(q)
        for i in range(len(q_array)):
            if i < 26:
                ma.append(np.nan)
                continue
            window = q_array[i-26:i+1]
            ma.append(np.dot(window, weights) / 351)
        
        ema_7 = EMA(pd.Series(ma), 7)
        return {'ma': ma, 'ema': ema_7.tolist()}

    async def stop(self):
        """停止策略"""
        self.running = False
        if self.main_task:
            await self.main_task
            self.main_task = None